import { isExternal } from "@/utils/validate";
import { mapTree, browse } from "xe-utils";
import _ from "lodash";
import dayjs from "dayjs";

/**
 * 对象和每个属性值是否为空
 * @param obj
 */
export const checkObjIsEmpty = (obj: any) => {
  if (_.isEmpty(obj)) return true;
  return Object.keys(obj).every(el => {
    return obj[el] !== 0 && (obj[el] === null || obj[el] === "");
  });
};

/**
 * @desc 去除空格
 * @param {string} str - 字符串
 * @param {string} pos - 去除空格的位置
 * pos="both": 去除两边空格
 * pos="left": 去除左边空格
 * pos="right": 去除右边空格
 * pos="all": 去除所有空格 */
type Pos = "both" | "left" | "right" | "all";
export function trim(str: string, pos: Pos = "both"): string {
  if (pos == "both") {
    return str.replace(/^\s+|\s+$/g, "");
  } else if (pos == "left") {
    return str.replace(/^\s*/, "");
  } else if (pos == "right") {
    return str.replace(/(\s*$)/g, "");
  } else if (pos == "all") {
    return str.replace(/\s+/g, "");
  } else {
    return str;
  }
}

/**
 * 根据数字获取对应的汉字
 * @param {number} num - 数字(0-10) */
export function getHanByNumber(num: number): string {
  const str = "零一二三四五六七八九十";
  return str.charAt(num);
}

/**
 * 获取指定整数范围内的随机整数
 * @param {number} start - 开始范围
 * @param {number} end - 结束范围 */
export function getRandomInterger(start = 0, end: number): number {
  const range = end - start;
  const random = Math.floor(Math.random() * range + start);
  return random;
}

/** @desc 千分位格式化 */
export function formatMoney(money: string) {
  return money.replace(new RegExp(`(?!^)(?=(\\d{3})+${money.includes(".") ? "\\." : "$"})`, "g"), ",");
}

/** @desc 数据类型检测方法 */
export function getTypeOf(value: any) {
  return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}

/**
 * @desc 格式化电话号码
 * @demo 183-7983-6654 */
export function formatPhone(mobile: string, formatStr = "-") {
  return mobile.replace(/(?=(\d{4})+$)/g, formatStr);
}

/**
 * @desc 手机号脱敏
 * @demo 155****8810  */
export function hidePhone(phone: string) {
  return phone.replace(/^(\d{3})\d{4}(\d{4})$/, "$1****$2");
}
export const hideMiddleDigits = (phoneNumber: string) => {
  if (phoneNumber?.length === 11) {
    return phoneNumber.slice(0, 3) + "****" + phoneNumber.slice(7);
  } else {
    console.error("手机号码格式不正确");
    return phoneNumber;
  }
};

/** @desc 检测数据是否为空数据 */
export function isEmpty(data: unknown) {
  if (data === "" || data === "undefined" || data === undefined || data === null || data === "null") {
    return true;
  }
  if (JSON.stringify(data) == "{}" || JSON.stringify(data) == "[]" || JSON.stringify(data) == "[{}]") {
    return true;
  }
  return false;
}

/**
 * @desc 大小写转换
 * @param {string} str 待转换的字符串
 * @param {number} type 1:全大写 2:全小写 3:首字母大写 */
export function toCase(str: string, type: number) {
  switch (type) {
    case 1:
      return str.toUpperCase();
    case 2:
      return str.toLowerCase();
    case 3:
      return str[0].toUpperCase() + str.substring(1).toLowerCase();
    default:
      return str;
  }
}

/**
 * @desc 获取随机数
 * @param {number} min 最小值
 * @param {number} max 最大值
 * */
export const randomNum = (min: number, max: number) => {
  return Math.floor(min + Math.random() * (max + 1 - min));
};

/**
 * @desc 获取最大值 */
export const max = (arr: number[]) => {
  return Math.max.apply(null, arr);
};

/**
 * @desc 获取最小值 */
export const min = (arr: number[]) => {
  return Math.min.apply(null, arr);
};

/**
 * @desc 求和 */
export const sum = (arr: number[]) => {
  return arr.reduce((pre, cur) => pre + cur);
};

/**
 * @desc 获取平均值 */
export const average = (arr: number[]) => {
  return sum(arr) / arr.length;
};

/**
 * @desc 文件大小格式化 */
export const formatFileSize = (size: number) => {
  const units = ["B", "KB", "MB", "GB"];
  let index = 0;
  while (size > 1024 && index < units.length) {
    size /= 1024;
    index++;
  }
  return Math.round(size * 100) / 100 + units[index];
};

/**
 * @desc 深拷贝 */
export const deepClone = (data: any) => {
  if (typeof data !== "object" || data === null) return "不是对象";
  const newData: any = Array.isArray(data) ? [] : {};
  for (const key in data) {
    newData[key] = typeof data[key] === "object" ? deepClone(data[key]) : data[key];
  }
  return newData;
};

/**
 * @desc 判断是否是闰年
 * @param {number} year 年份 */
export const isLeapYear = (year: number) => {
  return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
};

/**
 * @desc 判断是否是奇数
 * @param {number} num 数字 */
export const isOdd = (num: number) => {
  return num % 2 !== 0;
};

/**
 * @desc 判断是否是偶数
 * @param {number} num 数字 */
export const isEven = (num: number) => {
  return !isOdd(num);
};

/**
 * @desc 将RGB转化为十六机制 */
export const rgbToHex = (r: number, g: number, b: number) => {
  return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
};

/**
 * @desc 获取随机十六进制颜色 */
export const randomHex = () => {
  return `#${Math.floor(Math.random() * 0xffffff)
    .toString(16)
    .padEnd(6, "0")}`;
};

/**
 * @description 动态路由 path 转 name
 * @demo /system => System
 * @demo /system/menu => SystemMenu
 * @demo /data-manage/detail => DataManageDetail
 */
export const transformPathToName = (path: string) => {
  if (!path) return "";
  if (isExternal(path)) return "";
  return _.upperFirst(_.camelCase(path));
};

/**
 * @desc 过滤树
 * @param { values } 数组
 */
type FilterTree = <T extends { children?: T[] }>(array: T[], iterate: (item: T, index?: number, items?: T[]) => boolean) => T[];
export const filterTree: FilterTree = (values, fn) => {
  const arr = values.filter(fn);
  const data = mapTree(arr, item => {
    if (item.children && item.children.length) {
      item.children = item.children.filter(fn);
    }
    return item;
  });
  return data;
};

type SortTree = <T extends { sort: number; children?: T[] }>(array: T[]) => T[];
/**
 * @desc 排序树
 * @param { values } 数组
 */
export const sortTree: SortTree = values => {
  values?.sort((a, b) => (a?.sort ?? 0) - (b?.sort ?? 0)); // 排序
  return mapTree(values, item => {
    item.children?.sort((a, b) => (a?.sort ?? 0) - (b?.sort ?? 0)); // 排序
    return item;
  });
};

/** @desc 是否是h5环境 */
export const isMobile = () => {
  return browse().isMobile;
};

/** @desc 问候 */
export function goodTimeText() {
  const time = new Date();
  const hour = time.getHours();
  return hour < 9 ? "早上好" : hour <= 11 ? "上午好" : hour <= 13 ? "中午好" : hour < 20 ? "下午好" : "晚上好";
}

export const getFolder = (name = "mall") => {
  const today = new Date();
  const year = today.getFullYear();
  let month: string | number = today.getMonth() + 1; // 注意月份从0开始，所以要加1
  let date: string | number = today.getDate();
  if (month < 10) {
    month = "0" + month;
  }
  if (date < 10) {
    date = "0" + date;
  }
  const DATE = year + "-" + month + "-" + date;
  // console.log("当前年月日===", `/${name}/${DATE}/`);
  return `/${name}/${DATE}/`;
};

/**
 * 防抖
 */
export const _debounce = (fn, time) => {
  let timer = null;
  return (...args) => {
    const context = this;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.call(context, ...args);
    }, time);
  };
};
/**
 * 节流
 */
export const _throttle = (fn, time) => {
  let activeTime = null;
  return (...args) => {
    const context = this;
    const current = Date.now();
    if (current - activeTime >= time) {
      fn.call(context, ...args);
      activeTime = Date.now();
    }
  };
};
// 递归修改tree数据的指定属性和值
export const updateTreeValue = (node, newPropertyName, newValue) => {
  for (let item of node) {
    item[newPropertyName] = newValue;
    if (item.children) {
      updateTreeValue(item.children, newPropertyName, newValue);
    }
  }
};

// 组织结构子id，找父
export const orgChildIdFindParent = (childId, orgList = [], key = "stastsId") => {
  const result = findParentsId(orgList, childId, key);
  return result || [];
};
// 根据子id找父,返回值不包含查找的节点
const findParentsId = (treeData, id, key) => {
  if (treeData.length == 0) return;
  for (let i = 0; i < treeData.length; i++) {
    if (treeData[i][key] == id) {
      return [];
    } else {
      if (treeData[i].children) {
        let res = findParentsId(treeData[i].children, id, key);
        if (res !== undefined) {
          return res.concat({ ...treeData[i] }).reverse();
        }
      }
    }
  }
};

//tree获取本级和所有父级
export const findAncestorsById = (id, tree, key, result = []) => {
  for (const node of tree) {
    if (node[key] === id) {
      result.push(node);
      return result;
    }
    if (node.children) {
      const temp = findAncestorsById(id, node.children, key, result);
      if (temp) {
        result.unshift(node);
        return result;
      }
    }
  }
  return null;
};

/**
 * 随机生成ID
 * @return {string}
 */
export const generateId = () => {
  const str = [];
  const hexDigits = "0123456789abcdef";
  for (let i = 0; i < 36; i++) {
    str[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
  }
  str[14] = "4";
  str[19] = hexDigits.substr((str[19] & 0x3) | 0x8, 1);
  return str.join("");
};

/**
 * 解析字符串
 */
type ParseOrDefaultType = (str: string, defaultValue?: any) => any;
export const parseOrDefault: ParseOrDefaultType = (str, defaultValue = "") => {
  try {
    return JSON.parse(str) || defaultValue;
  } catch {
    return defaultValue;
  }
};

/**
 * 禁用之前的时间
 */
export const disabledDate = (current: any) => {
  return current.getTime() < Date.now() - 8.64e7;
};
export const disabledTime = (current: any) => {
  return {
    disabledHours: () => getDisabledHours(dayjs(current) || dayjs(new Date())),
    disabledMinutes: () => getDisabledMinutes(dayjs(current) || dayjs(new Date())),
    disabledSeconds: () => getDisabledSeconds(dayjs(current) || dayjs(new Date()))
  };
};
export const getDisabledHours = (date: any) => {
  const hours = [];
  for (let i = 0; i < 24; i++) {
    if (dayjs().isAfter(date.clone().hour(i))) {
      hours.push(i);
    }
  }
  return hours;
};
export const getDisabledMinutes = (date: any) => {
  const minutes = [];
  for (let i = 0; i < 60; i++) {
    if (dayjs().isAfter(date.clone().minute(i))) {
      minutes.push(i);
    }
  }
  return minutes;
};
export const getDisabledSeconds = (date: any) => {
  const seconds = [];
  for (let i = 0; i < 60; i++) {
    if (dayjs().isAfter(date.clone().second(i))) {
      seconds.push(i);
    }
  }
  return seconds;
};


export const treeToArr = source => {
  let res = [];
  source.forEach(el => {
    res.push(el);
    el.children && res.push(...treeToArr(el.children));
  });
  return res;
};